diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast.c | 121 | ||||
| -rw-r--r-- | src/ast.h | 9 | ||||
| -rw-r--r-- | src/compile/binops.c | 2 | ||||
| -rw-r--r-- | src/compile/files.c | 41 | ||||
| -rw-r--r-- | src/compile/reductions.c | 2 | ||||
| -rw-r--r-- | src/compile/statements.c | 49 | ||||
| -rw-r--r-- | src/environment.c | 6 | ||||
| -rw-r--r-- | src/formatter/formatter.c | 13 | ||||
| -rw-r--r-- | src/parse/expressions.c | 2 | ||||
| -rw-r--r-- | src/typecheck.c | 4 |
10 files changed, 104 insertions, 145 deletions
@@ -36,83 +36,46 @@ const int op_tightness[NUM_AST_TAGS] = { [Xor] = 1, }; -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; - } -} - -CONSTFUNC const char *binop_operator(ast_e tag) { - switch (tag) { - case Power: return "^"; - case PowerUpdate: return "^="; - case Concat: return "++"; - case ConcatUpdate: return "++="; - case Multiply: return "*"; - case MultiplyUpdate: return "*="; - case Divide: return "/"; - case DivideUpdate: return "/="; - case Mod: return "mod"; - case ModUpdate: return "mod="; - case Mod1: return "mod1"; - case Mod1Update: return "mod1="; - case Plus: return "+"; - case PlusUpdate: return "+="; - case Minus: return "-"; - case MinusUpdate: return "-="; - case LeftShift: return "<<"; - case LeftShiftUpdate: return "<<="; - case RightShift: return ">>"; - case RightShiftUpdate: return ">>="; - case And: return "and"; - case AndUpdate: return "and="; - case Or: return "or"; - case OrUpdate: return "or="; - case Xor: return "xor"; - case XorUpdate: return "xor="; - case Equals: return "=="; - case NotEquals: return "!="; - case LessThan: return "<"; - case LessThanOrEquals: return "<="; - case GreaterThan: return ">"; - case GreaterThanOrEquals: return ">="; - case Min: return "_min_"; - case Max: return "_max_"; - 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); static Text_t arg_list_to_sexp(arg_ast_t *args); @@ -122,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) { @@ -291,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_operator(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), ")"); @@ -481,6 +481,13 @@ struct ast_s { extern const int op_tightness[NUM_AST_TAGS]; +typedef struct { + const char *method_name; + const char *operator; +} binop_info_t; + +extern const binop_info_t binop_info[NUM_AST_TAGS]; + OptionalText_t ast_source(ast_t *ast); Text_t ast_to_sexp(ast_t *ast); @@ -490,7 +497,5 @@ Text_t type_ast_to_sexp(type_ast_t *ast); PUREFUNC bool is_idempotent(ast_t *ast); void visit_topologically(ast_list_t *ast, Closure_t fn); CONSTFUNC bool is_update_assignment(ast_t *ast); -CONSTFUNC const char *binop_method_name(ast_e tag); -CONSTFUNC const char *binop_operator(ast_e tag); CONSTFUNC ast_e binop_tag(ast_e tag); CONSTFUNC bool is_binary_operation(ast_t *ast); diff --git a/src/compile/binops.c b/src/compile/binops.c index 87fd2c7a..ed4aaeba 100644 --- a/src/compile/binops.c +++ b/src/compile/binops.c @@ -67,7 +67,7 @@ Text_t compile_binary_op(env_t *env, ast_t *ast) { } } } else if ((ast->tag == Divide || ast->tag == Mod || ast->tag == Mod1) && is_numeric_type(rhs_t)) { - b = get_namespace_binding(env, binop.lhs, binop_method_name(ast->tag)); + b = get_namespace_binding(env, binop.lhs, binop_info[ast->tag].method_name); if (b && b->type->tag == FunctionType) { DeclareMatch(fn, b->type, FunctionType); if (type_eq(fn->ret, lhs_t)) { diff --git a/src/compile/files.c b/src/compile/files.c index c250e6cc..3e91976b 100644 --- a/src/compile/files.c +++ b/src/compile/files.c @@ -12,7 +12,16 @@ #include "../types.h" #include "compilation.h" -static void initialize_vars_and_statics(env_t *env, ast_t *ast) { +static void initialize_vars_and_statics(env_t *env, ast_t *ast); +static void initialize_namespace(env_t *env, const char *name, ast_t *namespace); +static Text_t compile_top_level_code(env_t *env, ast_t *ast); +static Text_t compile_namespace(env_t *env, const char *name, ast_t *namespace); + +void initialize_namespace(env_t *env, const char *name, ast_t *namespace) { + initialize_vars_and_statics(namespace_env(env, name), namespace); +} + +void initialize_vars_and_statics(env_t *env, ast_t *ast) { if (!ast) return; for (ast_list_t *stmt = Match(ast, Block)->statements; stmt; stmt = stmt->next) { @@ -27,24 +36,20 @@ static void initialize_vars_and_statics(env_t *env, ast_t *ast) { if (t->tag == FunctionType) t = Type(ClosureType, t); Text_t val_code = compile_declared_value(env, stmt->ast); if ((decl->value && !is_constant(env, decl->value)) || (!decl->value && has_heap_memory(t))) { - Text_t initialized_name = namespace_name(env, env->namespace, Texts(decl_name, "$$initialized")); + Text_t initialized_name = namespace_name(env, env->namespace, Texts(decl_name, "$initialized")); env->code->variable_initializers = Texts(env->code->variable_initializers, with_source_info(env, stmt->ast, Texts(full_name, " = ", val_code, ",\n", initialized_name, " = true;\n"))); } } else if (stmt->ast->tag == StructDef) { - initialize_vars_and_statics(namespace_env(env, Match(stmt->ast, StructDef)->name), - Match(stmt->ast, StructDef)->namespace); + initialize_namespace(env, Match(stmt->ast, StructDef)->name, Match(stmt->ast, StructDef)->namespace); } else if (stmt->ast->tag == EnumDef) { - initialize_vars_and_statics(namespace_env(env, Match(stmt->ast, EnumDef)->name), - Match(stmt->ast, EnumDef)->namespace); + initialize_namespace(env, Match(stmt->ast, EnumDef)->name, Match(stmt->ast, EnumDef)->namespace); } else if (stmt->ast->tag == LangDef) { - initialize_vars_and_statics(namespace_env(env, Match(stmt->ast, LangDef)->name), - Match(stmt->ast, LangDef)->namespace); + initialize_namespace(env, Match(stmt->ast, LangDef)->name, Match(stmt->ast, LangDef)->namespace); } else if (stmt->ast->tag == Extend) { - initialize_vars_and_statics(namespace_env(env, Match(stmt->ast, Extend)->name), - Match(stmt->ast, Extend)->body); + initialize_namespace(env, Match(stmt->ast, Extend)->name, Match(stmt->ast, Extend)->body); } else if (stmt->ast->tag == Use) { continue; } else { @@ -54,7 +59,12 @@ static void initialize_vars_and_statics(env_t *env, ast_t *ast) { } } -static Text_t compile_top_level_code(env_t *env, ast_t *ast) { +Text_t compile_namespace(env_t *env, const char *name, ast_t *namespace) { + env_t *ns_env = namespace_env(env, name); + return namespace ? compile_top_level_code(ns_env, namespace) : EMPTY_TEXT; +} + +Text_t compile_top_level_code(env_t *env, ast_t *ast) { if (!ast) return EMPTY_TEXT; switch (ast->tag) { @@ -111,15 +121,13 @@ static Text_t compile_top_level_code(env_t *env, ast_t *ast) { type_t *t = Table$str_get(*env->types, def->name); assert(t && t->tag == StructType); Text_t code = compile_struct_typeinfo(env, t, def->name, def->fields, def->secret, def->opaque); - env_t *ns_env = namespace_env(env, def->name); - return Texts(code, def->namespace ? compile_top_level_code(ns_env, def->namespace) : EMPTY_TEXT); + return Texts(code, compile_namespace(env, def->name, def->namespace)); } case EnumDef: { DeclareMatch(def, ast, EnumDef); Text_t code = compile_enum_typeinfo(env, ast); code = Texts(code, compile_enum_constructors(env, ast)); - env_t *ns_env = namespace_env(env, def->name); - return Texts(code, def->namespace ? compile_top_level_code(ns_env, def->namespace) : EMPTY_TEXT); + return Texts(code, compile_namespace(env, def->name, def->namespace)); } case LangDef: { DeclareMatch(def, ast, LangDef); @@ -127,8 +135,7 @@ static Text_t compile_top_level_code(env_t *env, ast_t *ast) { Texts("public const TypeInfo_t ", namespace_name(env, env->namespace, Texts(def->name, "$$info")), " = {", (int64_t)sizeof(Text_t), ", ", (int64_t)__alignof__(Text_t), ", .metamethods=Text$metamethods, .tag=TextInfo, .TextInfo={", quoted_str(def->name), "}};\n"); - env_t *ns_env = namespace_env(env, def->name); - return Texts(code, def->namespace ? compile_top_level_code(ns_env, def->namespace) : EMPTY_TEXT); + return Texts(code, compile_namespace(env, def->name, def->namespace)); } case Extend: { DeclareMatch(extend, ast, Extend); diff --git a/src/compile/reductions.c b/src/compile/reductions.c index 1652384c..438e072b 100644 --- a/src/compile/reductions.c +++ b/src/compile/reductions.c @@ -12,7 +12,7 @@ public Text_t compile_reduction(env_t *env, ast_t *ast) { DeclareMatch(reduction, ast, Reduction); ast_e op = reduction->op; - const char *op_str = binop_operator(op); + const char *op_str = binop_info[op].operator; type_t *iter_t = get_type(env, reduction->iter); type_t *item_t = get_iterated_type(iter_t); diff --git a/src/compile/statements.c b/src/compile/statements.c index 4e37838c..bde9ae36 100644 --- a/src/compile/statements.c +++ b/src/compile/statements.c @@ -25,6 +25,14 @@ Text_t with_source_info(env_t *env, ast_t *ast, Text_t code) { return Texts("\n#line ", line, "\n", code); } +static Text_t compile_simple_update_assignment(env_t *env, ast_t *ast, const char *op) { + binary_operands_t update = BINARY_OPERANDS(ast); + type_t *lhs_t = get_type(env, update.lhs); + if (is_idempotent(update.lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) + return Texts(compile_lvalue(env, update.lhs), " ", op, "= ", compile_to_type(env, update.rhs, lhs_t), ";"); + return compile_update_assignment(env, ast); +} + static Text_t _compile_statement(env_t *env, ast_t *ast) { switch (ast->tag) { case When: return compile_when_statement(env, ast); @@ -47,41 +55,12 @@ static Text_t _compile_statement(env_t *env, ast_t *ast) { } } case Assign: return compile_assignment_statement(env, ast); - case PlusUpdate: { - DeclareMatch(update, ast, PlusUpdate); - type_t *lhs_t = get_type(env, update->lhs); - if (is_idempotent(update->lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) - return Texts(compile_lvalue(env, update->lhs), " += ", compile_to_type(env, update->rhs, lhs_t), ";"); - return compile_update_assignment(env, ast); - } - case MinusUpdate: { - DeclareMatch(update, ast, MinusUpdate); - type_t *lhs_t = get_type(env, update->lhs); - if (is_idempotent(update->lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) - return Texts(compile_lvalue(env, update->lhs), " -= ", compile_to_type(env, update->rhs, lhs_t), ";"); - return compile_update_assignment(env, ast); - } - case MultiplyUpdate: { - DeclareMatch(update, ast, MultiplyUpdate); - type_t *lhs_t = get_type(env, update->lhs); - if (is_idempotent(update->lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) - return Texts(compile_lvalue(env, update->lhs), " *= ", compile_to_type(env, update->rhs, lhs_t), ";"); - return compile_update_assignment(env, ast); - } - case DivideUpdate: { - DeclareMatch(update, ast, DivideUpdate); - type_t *lhs_t = get_type(env, update->lhs); - if (is_idempotent(update->lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) - return Texts(compile_lvalue(env, update->lhs), " /= ", compile_to_type(env, update->rhs, lhs_t), ";"); - return compile_update_assignment(env, ast); - } - case ModUpdate: { - DeclareMatch(update, ast, ModUpdate); - type_t *lhs_t = get_type(env, update->lhs); - if (is_idempotent(update->lhs) && (lhs_t->tag == IntType || lhs_t->tag == NumType || lhs_t->tag == ByteType)) - return Texts(compile_lvalue(env, update->lhs), " %= ", compile_to_type(env, update->rhs, lhs_t), ";"); - return compile_update_assignment(env, ast); - } + case PlusUpdate: return compile_simple_update_assignment(env, ast, "+"); + case MinusUpdate: return compile_simple_update_assignment(env, ast, "-"); + case MultiplyUpdate: return compile_simple_update_assignment(env, ast, "*"); + case DivideUpdate: return compile_simple_update_assignment(env, ast, "/"); + case ModUpdate: return compile_simple_update_assignment(env, ast, "%"); + case PowerUpdate: case Mod1Update: case ConcatUpdate: diff --git a/src/environment.c b/src/environment.c index 5efedfbe..7ac54a7a 100644 --- a/src/environment.c +++ b/src/environment.c @@ -73,7 +73,9 @@ env_t *global_env(bool source_mapping) { } ns_entry_t; #define MAKE_TYPE(name, type, type_name, type_info, ...) \ - {name, type, type_name, type_info, TypedList(ns_entry_t, __VA_ARGS__)} + { \ + name, type, type_name, type_info, TypedList(ns_entry_t, __VA_ARGS__) \ + } struct { const char *name; type_t *type; @@ -736,7 +738,7 @@ PUREFUNC binding_t *get_constructor(env_t *env, type_t *t, arg_ast_t *args, bool } PUREFUNC binding_t *get_metamethod_binding(env_t *env, ast_e tag, ast_t *lhs, ast_t *rhs, type_t *ret) { - const char *method_name = binop_method_name(tag); + const char *method_name = binop_info[tag].method_name; if (!method_name) return NULL; binding_t *b = get_namespace_binding(env, lhs, method_name); if (!b || b->type->tag != FunctionType) return NULL; diff --git a/src/formatter/formatter.c b/src/formatter/formatter.c index 60714945..b68b3874 100644 --- a/src/formatter/formatter.c +++ b/src/formatter/formatter.c @@ -323,7 +323,8 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { if (reduction->key) { return Texts("(", fmt_inline(reduction->key, comments), ": ", fmt_inline(reduction->iter, comments)); } else { - return Texts("(", binop_operator(reduction->op), ": ", fmt_inline(reduction->iter, comments)); + return Texts("(", Text$from_str(binop_info[reduction->op].operator), ": ", + fmt_inline(reduction->iter, comments)); } } /*inline*/ case None: @@ -353,7 +354,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { } /*inline*/ case BINOP_CASES: { binary_operands_t operands = BINARY_OPERANDS(ast); - const char *op = binop_operator(ast->tag); + const char *op = binop_info[ast->tag].operator; Text_t lhs = fmt_inline(operands.lhs, comments); Text_t rhs = fmt_inline(operands.rhs, comments); @@ -368,7 +369,7 @@ OptionalText_t format_inline_code(ast_t *ast, Table_t comments) { rhs = parenthesize(rhs, EMPTY_TEXT); Text_t space = op_tightness[ast->tag] >= op_tightness[Multiply] ? EMPTY_TEXT : Text(" "); - return Texts(lhs, space, Text$from_str(binop_operator(ast->tag)), space, rhs); + return Texts(lhs, space, Text$from_str(binop_info[ast->tag].operator), space, rhs); } /*inline*/ case Deserialize: { DeclareMatch(deserialize, ast, Deserialize); @@ -760,7 +761,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) { return Texts("(", fmt(reduction->key, comments, Texts(indent, single_indent)), ": ", fmt(reduction->iter, comments, Texts(indent, single_indent))); } else { - return Texts("(", binop_operator(reduction->op), ": ", + return Texts("(", binop_info[reduction->op].operator, ": ", fmt(reduction->iter, comments, Texts(indent, single_indent))); } } @@ -808,7 +809,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) { /*multiline*/ case BINOP_CASES: { if (inlined_fits) return inlined; binary_operands_t operands = BINARY_OPERANDS(ast); - const char *op = binop_operator(ast->tag); + const char *op = binop_info[ast->tag].operator; Text_t lhs = fmt(operands.lhs, comments, indent); Text_t rhs = fmt(operands.rhs, comments, indent); @@ -822,7 +823,7 @@ Text_t format_code(ast_t *ast, Table_t comments, Text_t indent) { rhs = parenthesize(rhs, indent); Text_t space = op_tightness[ast->tag] >= op_tightness[Multiply] ? EMPTY_TEXT : Text(" "); - return Texts(lhs, space, Text$from_str(binop_operator(ast->tag)), space, rhs); + return Texts(lhs, space, Text$from_str(binop_info[ast->tag].operator), space, rhs); } /*multiline*/ case Deserialize: { if (inlined_fits) return inlined; diff --git a/src/parse/expressions.c b/src/parse/expressions.c index 32133fe9..df0a10a7 100644 --- a/src/parse/expressions.c +++ b/src/parse/expressions.c @@ -49,7 +49,7 @@ ast_t *parse_reduction(parse_ctx_t *ctx, const char *pos) { ast_e op = match_binary_operator(&pos); if (op == Unknown) return NULL; - const char *op_str = binop_operator(op); + const char *op_str = binop_info[op].operator; assert(op_str); ast_t *key = NewAST(ctx->file, pos, pos, Var, .name = op_str); for (bool progress = true; progress;) { diff --git a/src/typecheck.c b/src/typecheck.c index 2d805cdb..e34a85de 100644 --- a/src/typecheck.c +++ b/src/typecheck.c @@ -1356,7 +1356,7 @@ type_t *get_type(env_t *env, ast_t *ast) { } } } else if ((ast->tag == Divide || ast->tag == Mod || ast->tag == Mod1) && is_numeric_type(rhs_t)) { - binding_t *b = get_namespace_binding(env, binop.lhs, binop_method_name(ast->tag)); + binding_t *b = get_namespace_binding(env, binop.lhs, binop_info[ast->tag].method_name); if (b && b->type->tag == FunctionType) { DeclareMatch(fn, b->type, FunctionType); if (type_eq(fn->ret, lhs_t)) { @@ -1415,7 +1415,7 @@ type_t *get_type(env_t *env, ast_t *ast) { code_err(reduction->iter, "I don't know how to do a reduction over ", type_to_str(iter_t), " values"); if (reduction->key && !(reduction->op == Min || reduction->op == Max)) { env_t *item_scope = fresh_scope(env); - const char *op_str = binop_operator(reduction->op); + const char *op_str = binop_info[reduction->op].operator; set_binding(item_scope, op_str, iterated, EMPTY_TEXT); iterated = get_type(item_scope, reduction->key); } |
